<script setup>
import { ref, watch, onMounted } from 'vue'
import { Microphone, Position, Upload } from '@element-plus/icons-vue'
import ChatMessage from '@/components/ChatMessage.vue'
import { getRolePresetList } from '@/api/rolePreset.js'
import { useRouter } from 'vue-router'
import { Collection } from '@element-plus/icons-vue'
import { getKnowledgeByRole } from '@/api/knowledge'
import { ElMessage } from 'element-plus'
import { streamChat, handleStreamResponse } from '@/api/chat'
import { generateId } from '@/utils/snowflake' // 导入SnowFlake ID生成器
import { voiceChat } from '@/api/voice' // 导入语音聊天API

// 路由
const router = useRouter()

// 接收父组件传递的属性
const props = defineProps({
  selectedCharacter: Object,
  chatMessages: Array,
  loading: Boolean,
  currentConversationId: String
})

// 聊天输入
const chatInput = ref('')

// 是否正在录音
const isRecording = ref(false)

// 语音相关变量
const mediaRecorder = ref(null)
const audioChunks = ref([])
const recordedAudio = ref(null)

// 角色列表
const roleList = ref([])
// 选中的角色ID
const selectedRoleId = ref('')
// 加载角色列表状态
const loadingRoles = ref(false)

const hasKnowledge = ref(false)
const useKnowledge = ref(true)

// 检查角色是否有知识库
const checkKnowledgeStatus = async () => {
  if (!props.selectedCharacter?.id) return

  try {
    const res = await getKnowledgeByRole(props.selectedCharacter.id)
    hasKnowledge.value = res.data && res.data.length > 0
  } catch (error) {
    hasKnowledge.value = false
  }
}

// 切换知识库模式
const toggleKnowledgeMode = () => {
  useKnowledge.value = !useKnowledge.value
  ElMessage.success(useKnowledge.value ? '已启用知识库' : '已禁用知识库')
}

// 组件挂载时获取角色列表
onMounted(() => {
  // 如果已有选中角色，设置selectedRoleId
  if (props.selectedCharacter && props.selectedCharacter.id) {
    selectedRoleId.value = props.selectedCharacter.id
  }
})

// 监听selectedCharacter变化
watch(() => props.selectedCharacter, (newVal) => {
  if (newVal && newVal.id) {
    selectedRoleId.value = newVal.id
  } else {
    selectedRoleId.value = ''
  }
}, { immediate: true })

// 跳转到角色广场
const goToRoleSquare = () => {
  emit('show-role-square')
}

// 定义事件
const emit = defineEmits(['send-message', 'role-selected', 'show-role-square', 'add-message', 'update-message', 'remove-message', 'conversation-updated'])

// 开始/停止录音
const toggleRecording = async () => {
  try {
    if (!isRecording.value) {
      await startRecording()
    } else {
      await stopRecording()
    }
  } catch (error) {
    console.error('录音操作失败:', error)
    ElMessage.error('录音操作失败: ' + error.message)
  }
}

// 开始录音
const startRecording = async () => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true })

    mediaRecorder.value = new MediaRecorder(stream)
    audioChunks.value = []

    mediaRecorder.value.ondataavailable = (event) => {
      if (event.data.size > 0) {
        audioChunks.value.push(event.data)
      }
    }

    mediaRecorder.value.onstop = async () => {
      const audioBlob = new Blob(audioChunks.value, { type: 'audio/wav' })
      recordedAudio.value = audioBlob

      // 停止所有音频轨道
      stream.getTracks().forEach(track => track.stop())

      // 自动处理录音
      await handleRecordedAudio()
    }

    mediaRecorder.value.start()
    isRecording.value = true
    ElMessage.success('开始录音...')

  } catch (error) {
    console.error('无法访问麦克风:', error)
    ElMessage.error('无法访问麦克风，请检查权限设置')
  }
}

// 停止录音
const stopRecording = () => {
  if (mediaRecorder.value && isRecording.value) {
    mediaRecorder.value.stop()
    isRecording.value = false
    ElMessage.info('录音结束，正在处理...')
  }
}

// 处理录音结果
const handleRecordedAudio = async () => {
  if (!recordedAudio.value) return

  try {
    sending.value = true

    // 添加用户录音消息
    const userMessage = {
      id: generateId(),
      type: 'user',
      content: '[🎤 语音消息]',
      timestamp: new Date().toISOString()
    }
    emit('add-message', userMessage)

    // 添加AI思考状态
    const aiMessage = {
      id: generateId(),
      type: 'ai',
      content: '',
      timestamp: new Date().toISOString(),
      loading: true
    }
    emit('add-message', aiMessage)

    // 调用语音聊天API
    const response = await voiceChat(
      recordedAudio.value,
      props.currentConversationId || generateId(),
      selectedRoleId.value
    )

    if (response.code === 200) {
      const data = response.data

      // 更新用户消息为转换后的文字
      userMessage.content = data.userText
      emit('update-message', userMessage)

      // 更新AI回复
      aiMessage.loading = false
      aiMessage.content = data.aiText
      emit('update-message', aiMessage)

      // 播放AI语音回复
      if (data.aiAudio) {
        playAudioFromBase64(data.aiAudio, data.aiAudioMimeType)
      }

      // 通知父组件更新会话列表
      emit('conversation-updated', {
        conversationId: props.currentConversationId || generateId(),
        roleId: selectedRoleId.value,
        lastMessage: data.userText
      })
    } else {
      throw new Error(response.message || '语音聊天失败')
    }

  } catch (error) {
    console.error('语音聊天失败:', error)
    ElMessage.error('语音聊天失败: ' + error.message)

    // 移除失败的消息
    emit('remove-message', userMessage.id)
    emit('remove-message', aiMessage.id)
  } finally {
    sending.value = false
    recordedAudio.value = null
  }
}

// 从Base64播放音频
const playAudioFromBase64 = (base64Audio, mimeType = 'audio/wav') => {
  try {
    const audioData = atob(base64Audio)
    const audioArray = new Uint8Array(audioData.length)
    for (let i = 0; i < audioData.length; i++) {
      audioArray[i] = audioData.charCodeAt(i)
    }

    const audioBlob = new Blob([audioArray], { type: mimeType })
    playAudioFromBlob(audioBlob)
  } catch (error) {
    console.error('音频解码失败:', error)
    ElMessage.error('音频播放失败')
  }
}

// 从Blob播放音频
const playAudioFromBlob = (audioBlob) => {
  try {
    const audioUrl = URL.createObjectURL(audioBlob)
    const audio = new Audio(audioUrl)

    audio.onended = () => {
      URL.revokeObjectURL(audioUrl)
    }

    audio.onerror = () => {
      URL.revokeObjectURL(audioUrl)
      ElMessage.error('音频播放失败')
    }

    audio.play()

  } catch (error) {
    console.error('音频播放失败:', error)
    ElMessage.error('音频播放失败')
  }
}

// 发送消息
// 添加发送状态
const sending = ref(false)

// 修改发送消息方法
const sendMessage = async () => {
  if (!chatInput.value.trim()) return
  if (!selectedRoleId.value) {
    ElMessage.warning('请先选择一个角色')
    return
  }
  if (sending.value) return

  const userMessage = chatInput.value.trim()
  chatInput.value = ''
  sending.value = true

  try {
    // 1. 添加用户消息到聊天记录 - 使用SnowFlake ID
    const userMsg = {
      id: generateId(), // 使用SnowFlake生成唯一ID
      type: 'user',
      content: userMessage,
      timestamp: new Date().toISOString()
    }
    emit('add-message', userMsg)

    // 2. 创建AI消息占位符 - 使用SnowFlake ID
    const aiMsg = {
      id: generateId(), // 使用SnowFlake生成唯一ID
      type: 'ai',
      content: '',
      timestamp: new Date().toISOString(),
      loading: true
    }
    emit('add-message', aiMsg)

    // 3. 根据知识库模式选择API端点
    const apiEndpoint = useKnowledge.value && hasKnowledge.value
      ? '/chat/chat'        // 带知识库的聊天
      : '/chat/chat/simple' // 普通聊天

    // 4. 构建请求参数 - 会话ID也可以使用SnowFlake生成
    const requestParams = {
      memoryId: props.currentConversationId || generateId(), // 使用SnowFlake生成会话ID
      roleId: selectedRoleId.value,
      message: userMessage
    }

    // 5. 发送流式请求
    const response = await fetch(`${import.meta.env.VITE_BASE_API}${apiEndpoint}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
        'Authorization': localStorage.getItem('token') || ''
      },
      body: JSON.stringify(requestParams)
    })

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    // 6. 处理流式响应
    await handleStreamResponse(
      response,
      (chunk) => {
        // 更新AI消息内容
        aiMsg.content += chunk
        emit('update-message', aiMsg)
      },
      () => {
        // 完成时移除loading状态
        aiMsg.loading = false
        emit('update-message', aiMsg)

        // 通知父组件更新会话列表
        emit('conversation-updated', {
          conversationId: requestParams.memoryId,
          roleId: selectedRoleId.value,
          lastMessage: userMessage
        })
      }
    )

  } catch (error) {
    console.error('发送消息失败:', error)
    ElMessage.error('发送消息失败，请重试')

    // 移除失败的AI消息
    emit('remove-message', aiMsg.id)
  } finally {
    sending.value = false
  }
}

// 消息容器引用
const messageContainer = ref(null)

// 监听消息变化，自动滚动到底部
watch(() => props.chatMessages, () => {
  setTimeout(() => {
    if (messageContainer.value) {
      messageContainer.value.scrollTop = messageContainer.value.scrollHeight
    }
  }, 100)
}, { deep: true })

// 监听角色变化
watch(() => props.selectedCharacter, checkKnowledgeStatus, { immediate: true })
</script>

<template>
  <div class="chat-container">
    <div class="chat-header">
      <h2>{{ props.selectedCharacter ? props.selectedCharacter.name : 'AI角色扮演' }}</h2>
    </div>

    <div class="chat-messages" ref="messageContainer">
      <div v-if="loading" class="loading-container">
        <el-skeleton :rows="3" animated />
      </div>

      <div v-else-if="!chatMessages || chatMessages.length === 0" class="welcome-message">
        <h3>有什么可以帮忙的?</h3>
        <div class="role-selector">
          <div v-if="props.selectedCharacter" class="selected-role-info">
            <span class="selected-role-label">当前角色:</span>
            <el-tag size="large" type="success" class="selected-role-tag">{{ props.selectedCharacter.name }}</el-tag>
          </div>
          <el-button
            class="glass-button role-select-btn"
            @click="goToRoleSquare"
            :icon="props.selectedCharacter ? 'el-icon-refresh' : ''"
          >
            {{ props.selectedCharacter ? '更换角色' : '选择角色' }}
          </el-button>
        </div>
      </div>

      <ChatMessage
        v-for="message in chatMessages"
        :key="message.id"
        :message="message"
      />
    </div>

    <!-- 移除template包装，直接使用div -->
    <div class="chat-input-area">
      <div class="input-header">
        <div class="knowledge-status" v-if="props.selectedCharacter">
          <el-tag :type="hasKnowledge ? 'success' : 'info'" size="small">
            <el-icon><Collection /></el-icon>
            {{ hasKnowledge ? '知识库已启用' : '暂无知识库' }}
          </el-tag>
          <el-button
            v-if="hasKnowledge"
            size="small"
            text
            @click="toggleKnowledgeMode"
          >
            {{ useKnowledge ? '禁用知识库' : '启用知识库' }}
          </el-button>
        </div>
      </div>
      <div class="input-header" v-if="!selectedRoleId && (chatMessages && chatMessages.length > 0)">
        <div class="role-selector-small">
          <el-button
            class="glass-button-small role-select-btn-small"
            @click="goToRoleSquare"
          >
            选择角色
          </el-button>
        </div>
      </div>
      <el-input
        v-model="chatInput"
        placeholder="输入消息或点击麦克风开始语音聊天..."
        class="chat-input"
        @keyup.enter="sendMessage"
        :disabled="!selectedRoleId || sending"
      >
        <template #append>
          <el-button
            :icon="Microphone"
            :class="{ recording: isRecording }"
            @click="toggleRecording"
            :disabled="!selectedRoleId || sending"
            :title="isRecording ? '停止录音' : '开始录音'"
          />
        </template>
      </el-input>
    </div>
  </div>
</template>

<style scoped>
.chat-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  background-color: var(--el-bg-color);
  color: var(--el-text-color-primary);
  height: 100%;
}

.chat-messages {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  min-height: 0;
}

.chat-input-area {
  padding: 16px;
  border-top: 1px solid var(--el-border-color-light);
  background-color: var(--el-bg-color);
  flex-shrink: 0;
}

.chat-header {
  padding: 16px;
  border-bottom: 1px solid var(--el-border-color-light);
  display: flex;
  align-items: center;
  justify-content: center;
}

.chat-header h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 500;
}

.chat-messages {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-height: calc(100vh - 180px);
}

.welcome-message {
  text-align: center;
  margin: auto;
  color: var(--el-text-color-secondary);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.role-selector {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.selected-role-info {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 5px;
}

.selected-role-label {
  font-size: 16px;
  color: var(--el-text-color-secondary);
}

.selected-role-tag {
  font-size: 16px;
  padding: 8px 16px;
  border-radius: 8px;
}

.glass-button {
  height: 48px;
  min-width: 180px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  font-weight: 500;
  font-size: 16px;
  text-align: center;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  background: rgba(64, 158, 255, 0.8);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
}

.glass-button:hover {
  background: rgba(64, 158, 255, 0.9);
  transform: translateY(-2px);
  box-shadow: 0 10px 30px 0 rgba(64, 158, 255, 0.3);
}

.glass-button-small {
  height: 40px;
  min-width: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  font-weight: 500;
  font-size: 14px;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  background: rgba(64, 158, 255, 0.8);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
}

.glass-button-small:hover {
  background: rgba(64, 158, 255, 0.9);
  transform: translateY(-2px);
}

.role-selector-small {
  display: flex;
  justify-content: center;
  margin-bottom: 12px;
}

.role-select-btn-small {
  min-width: 100px;
}

.loading-container {
  padding: 20px;
  width: 100%;
}

.chat-input-area {
  padding: 16px;
  border-top: 1px solid var(--el-border-color-light);
}

.input-header {
  margin-bottom: 8px;
}

.chat-input {
  width: 100%;
}

.input-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 8px;
}

.recording {
  color: #f56c6c;
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}
</style>







